package org.nuonuo.sdk.client;


import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * @Version 1.0
 * @Author az
 * @Date 2024-03-28 11:06:11
 * @ClassName HttpConnPool
 * @Description
 */

final class HttpConnPool {
    private static final int CONNECT_TIMEOUT = 5000;
    private static final int Max_PRE_ROUTE = 50;
    private static final int MAX_CONN = 100;
    private static final int MAX_ROUTE = 100;
    private static CloseableHttpClient httpClient;
    private static PoolingHttpClientConnectionManager manager;
    private static final Object syncLock = new Object();

    HttpConnPool() {
    }

    static void setRequestConfig(HttpRequestBase httpRequestBase, HttpHost proxy, int... timeout) {
        int SOCKET_TIMEOUT = 30000;
        if (timeout != null && timeout.length == 1) {
            SOCKET_TIMEOUT = timeout[0] * 1000;
        }

        RequestConfig.Builder builder = RequestConfig.custom().setConnectionRequestTimeout(5000).setConnectTimeout(5000).setSocketTimeout(SOCKET_TIMEOUT);
        builder = proxy == null ? builder : builder.setProxy(proxy);
        httpRequestBase.setConfig(builder.build());
    }

    static CloseableHttpClient getHttpClient(String url) {
        if (httpClient == null) {
            synchronized(syncLock) {
                if (httpClient == null) {
                    String hostName = url.split("/")[2];
                    int port = 80;
                    if (hostName.contains(":")) {
                        String[] args = hostName.split(":");
                        hostName = args[0];
                        port = Integer.parseInt(args[1]);
                    }

                    httpClient = createHttpClient(hostName, port);
                    ScheduledExecutorService monitorExecutor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
                        public Thread newThread(Runnable r) {
                            Thread t = Executors.defaultThreadFactory().newThread(r);
                            t.setDaemon(true);
                            return t;
                        }
                    });
                    int idleTimeout = 360000;
                    int initialDelay = 360000;
                    int period = 360000;
                    monitorExecutor.scheduleAtFixedRate(() -> {
                        HttpConnPool.manager.closeExpiredConnections();
                        HttpConnPool.manager.closeIdleConnections(idleTimeout, TimeUnit.MILLISECONDS);
                    }, initialDelay, period, TimeUnit.MILLISECONDS);
                }
            }
        }

        return httpClient;
    }

    private static CloseableHttpClient createHttpClient(String host, int port) {
        ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();

        RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.create();
        manager = new PoolingHttpClientConnectionManager(builder.register("https", new SSLConnectionSocketFactory(sslnoConfig())).register("http", plainsf).build());
        manager.setMaxTotal(100);
        manager.setDefaultMaxPerRoute(50);
        HttpHost httpHost = new HttpHost(host, port);
        manager.setMaxPerRoute(new HttpRoute(httpHost), 100);
        return HttpClients.custom().setConnectionManager(manager).build();
    }

    private static SSLContext sslnoConfig() {
        final X509Certificate[] enpty = new X509Certificate[0];
        SSLContext ctx = null;

        try {
            ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return enpty;
                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
        } catch (Exception var3) {
            var3.printStackTrace();
        }

        return ctx;
    }
}
